//
//  ImageKit.m
//  YuanXinKit
//
//  Created by GJS on 2019/8/19.
//  Copyright © 2019 晏德智. All rights reserved.
//

#import "ImageKit.h"
#import <ImageIO/ImageIO.h>

#if __has_include(<React/RCTImageLoader.h>)
#import <React/RCTImageLoader.h>
#import <React/RCTImageSource.h>
#else
#import <React/RCTImageLoader.h>
#import <React/RCTImageSource.h>
#endif

#import <React/RCTImageStoreManager.h>

@implementation ImageKit

RCT_EXPORT_MODULE();

@synthesize bridge = _bridge;
@synthesize methodQueue = _methodQueue;

- (NSString *)safeDetectorQrCodeImage:(UIImage *)image {
    UIImage *rotatedImage = [self rotateImage:image options:@{@"rotation": @(90)}];
    NSString *qrCodeUrl = [self detectorQrCodeImage:rotatedImage];
    if (qrCodeUrl == nil) {
        rotatedImage = [self rotateImage:image options:@{@"rotation": @(0)}];
        qrCodeUrl = [self detectorQrCodeImage:rotatedImage];
    }
    if (qrCodeUrl == nil) {
        rotatedImage = [self rotateImage:image options:@{@"rotation": @(180)}];
        qrCodeUrl = [self detectorQrCodeImage:rotatedImage];
    }
    if (qrCodeUrl == nil) {
        rotatedImage = [self rotateImage:image options:@{@"rotation": @(270)}];
        qrCodeUrl = [self detectorQrCodeImage:rotatedImage];
    }
    
    return qrCodeUrl;
}

- (NSString *)detectorQrCodeImage2:(UIImage *)image {
    NSString *qrCodeUrl = nil;
    CIContext *context = [CIContext contextWithOptions:nil];
    CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:context options:@{CIDetectorAccuracy : CIDetectorAccuracyHigh}];// 二维码识别
    CIImage *superImage = [CIImage imageWithCGImage:image.CGImage];
    CIFilter *lighten = [CIFilter filterWithName:@"CIColorControls"];
    [lighten setValue:superImage forKey:kCIInputImageKey];
    float i = 0;
    while (i <= 4) {
        //修改照片对比度参数 0---4
        [lighten setValue:@(i) forKey:@"inputContrast"];
        CIImage *result = [lighten valueForKey:kCIOutputImageKey];
        CGImageRef cgImage = [context createCGImage:result fromRect:[superImage extent]];
        //修改后的照片
        //image = [UIImage imageWithCGImage:cgImage];
        NSArray *features = [detector featuresInImage:[CIImage imageWithCGImage:cgImage]];
        CGImageRelease(cgImage);
        if (features.count >= 1) {
            CIQRCodeFeature *feature = [features firstObject];
            NSString *scannedResult = feature.messageString;
            qrCodeUrl = scannedResult;
            return qrCodeUrl;
        }
        //变化区间可以自行设置
        i = i+0.5;
    }
    
    return qrCodeUrl;
}

- (NSString *)detectorQrCodeImage:(UIImage *)image {
    NSString *qrCodeUrl = nil;
    CIImage *ciImage = [[CIImage alloc] initWithCGImage:image.CGImage options:nil];
    //UIImage *rotateImage = [self rotateImage:image options:@{@"rotation": @(90)}];
    //CIImage *ciImage = [[CIImage alloc] initWithImage:rotateImage];
    CIContext *ciContext = [CIContext contextWithOptions:@{kCIContextUseSoftwareRenderer : @(YES)}]; // 软件渲染
    CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:ciContext options:@{CIDetectorAccuracy : CIDetectorAccuracyHigh}];// 二维码识别
    
//    //CUSTOM CODE TO ADD WHITE BACKGROUND
//    CIFilter *filter = [CIFilter filterWithName:@"CISourceAtopCompositing"];
//    [filter setDefaults];
//    CIColor *whiteColor = [[CIColor alloc] initWithColor:[UIColor whiteColor]];
//    CIImage *colorImage = [CIImage imageWithColor:whiteColor];
//
//    colorImage = [colorImage imageByCroppingToRect:ciImage.extent];
//    [filter setValue:ciImage forKey:kCIInputImageKey];
//    [filter setValue:colorImage forKey:kCIInputBackgroundImageKey];
//    CIImage *newImage = [filter valueForKey:kCIOutputImageKey];
    
    //NSDictionary *options = @{CIDetectorImageOrientation: @([self CGImagePropertyOrientation:image.imageOrientation])};
    NSArray *features = [detector featuresInImage:ciImage options:nil];
    if (features.count) {
        for (CIFeature *feature in features) {
            if ([feature isKindOfClass:[CIQRCodeFeature class]]) {
                //NSLog(@"qrCodeUrl = %@",((CIQRCodeFeature *)feature).messageString); // 打印二维码中的信息
                qrCodeUrl = ((CIQRCodeFeature *)feature).messageString;
                break;
            }
        }
    } else {
        NSLog(@"图片中没有二维码");
    }
    
    return qrCodeUrl;
}

- (CGImagePropertyOrientation)CGImagePropertyOrientation:(UIImageOrientation)orientation
{
    switch (orientation) {
        case UIImageOrientationUp:
            return kCGImagePropertyOrientationUp;
        case UIImageOrientationUpMirrored:
            return kCGImagePropertyOrientationUpMirrored;
        case UIImageOrientationDown:
            return kCGImagePropertyOrientationDown;
        case UIImageOrientationDownMirrored:
            return kCGImagePropertyOrientationDownMirrored;
        case UIImageOrientationLeftMirrored:
            return kCGImagePropertyOrientationLeftMirrored;
        case UIImageOrientationRight:
            return kCGImagePropertyOrientationRight;
        case UIImageOrientationRightMirrored:
            return kCGImagePropertyOrientationRightMirrored;
        case UIImageOrientationLeft:
            return kCGImagePropertyOrientationLeft;
    }
}

- (UIImage *)rotateImage:(UIImage *)image options:(NSDictionary *)options {
    BOOL mirrorImage = options[@"mirrorImage"];
    NSData *imageData = UIImageJPEGRepresentation(image, 1.0);
    // Create image source
    CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)imageData, NULL);
    //get all the metadata in the image
    NSMutableDictionary *imageMetadata = [(NSDictionary *) CFBridgingRelease(CGImageSourceCopyPropertiesAtIndex(source, 0, NULL)) mutableCopy];
    
    // create cgimage
    CGImageRef CGImage;
    CGImage = CGImageSourceCreateImageAtIndex(source, 0, NULL);
    
    // Rotate it
    CGImageRef rotatedCGImage;
    if ([options objectForKey:@"rotation"]) {
        float rotation = [[options objectForKey:@"rotation"] floatValue];
        rotatedCGImage = [self newCGImageRotatedByAngle:CGImage angle:rotation mirrorImage:mirrorImage];
    } else {
        // Get metadata orientation
        int metadataOrientation = [[imageMetadata objectForKey:(NSString *)kCGImagePropertyOrientation] intValue];
        
        if (metadataOrientation == 6) {
            rotatedCGImage = [self newCGImageRotatedByAngle:CGImage angle:270 mirrorImage:mirrorImage];
        } else if (metadataOrientation == 1) {
            rotatedCGImage = [self newCGImageRotatedByAngle:CGImage angle:0 mirrorImage:mirrorImage];
        } else if (metadataOrientation == 3) {
            rotatedCGImage = [self newCGImageRotatedByAngle:CGImage angle:180 mirrorImage:mirrorImage];
        } else {
            rotatedCGImage = [self newCGImageRotatedByAngle:CGImage angle:0 mirrorImage:mirrorImage];
        }
    }
    UIImage *rotatedImage = [UIImage imageWithCGImage:rotatedCGImage];
    CGImageRelease(CGImage);
    CGImageRelease(rotatedCGImage);
    return rotatedImage;
}

- (CGImageRef)newCGImageRotatedByAngle:(CGImageRef)imgRef angle:(CGFloat)angle mirrorImage:(BOOL)mirrorImage
{
    CGFloat angleInRadians = angle * (M_PI / 180);
    CGFloat width = CGImageGetWidth(imgRef);
    CGFloat height = CGImageGetHeight(imgRef);
    
    CGRect imgRect = CGRectMake(0, 0, width, height);
    CGAffineTransform transform = CGAffineTransformMakeRotation(angleInRadians);
    CGRect rotatedRect = CGRectApplyAffineTransform(imgRect, transform);
    
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef bmContext = CGBitmapContextCreate(NULL, rotatedRect.size.width, rotatedRect.size.height, 8, 0, colorSpace, (CGBitmapInfo) kCGImageAlphaPremultipliedFirst);
    
    if (mirrorImage) {
        CGAffineTransform transform = CGAffineTransformMakeTranslation(rotatedRect.size.width, 0.0);
        transform = CGAffineTransformScale(transform, -1.0, 1.0);
        CGContextConcatCTM(bmContext, transform);
    }
    
    CGContextSetAllowsAntialiasing(bmContext, TRUE);
    CGContextSetInterpolationQuality(bmContext, kCGInterpolationNone);
    
    CGColorSpaceRelease(colorSpace);
    
    CGContextTranslateCTM(bmContext, +(rotatedRect.size.width/2), +(rotatedRect.size.height/2));
    CGContextRotateCTM(bmContext, angleInRadians);
    CGContextTranslateCTM(bmContext, -(rotatedRect.size.width/2), -(rotatedRect.size.height/2));
    
    CGContextDrawImage(bmContext, CGRectMake((rotatedRect.size.width-width)/2.0f, (rotatedRect.size.height-height)/2.0f, width, height), imgRef);
    
    CGImageRef rotatedImage = CGBitmapContextCreateImage(bmContext);
    CFRelease(bmContext);
    return rotatedImage;
}

- (UIImage *)scaleQRImage:(UIImage *)image widthOrHeight:(CGFloat)widthOrHeight {
    UIImage *bigImage = image;
    float actualHeight = bigImage.size.height;
    float actualWidth = bigImage.size.width;
    float newWidth = widthOrHeight;
    float newHeight = widthOrHeight;
    if(actualWidth > actualHeight) {
        //宽图
        newWidth = actualWidth / actualHeight * newHeight;
    }
    else
    {
        //长图
        newHeight = actualHeight / actualWidth * newWidth;
    }
    CGRect rect = CGRectMake(0.0, 0.0, newWidth, newHeight);
    UIGraphicsBeginImageContext(rect.size);
    [bigImage drawInRect:rect];// scales image to rect
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    //RETURN
    return newImage;
}

- (void)getImage:(NSString *)filePath finishBlock:(void(^)(UIImage *image))block {
    UIImage *image = [[UIImage alloc] initWithContentsOfFile:filePath];
    if (image == nil) {
        NSURL *imageURL = [NSURL URLWithString:filePath];
        NSURLRequest *request = [[NSURLRequest alloc] initWithURL:imageURL];
        [self.bridge.imageLoader loadImageWithURLRequest:request callback:^(NSError *error, UIImage *image) {
            if (image == nil) {
                [self.bridge.imageStoreManager getImageDataForTag:filePath withBlock:^(NSData *imageData) {
                    RCTExecuteOnMainQueue(^{
                        if (block) {
                            block([UIImage imageWithData:imageData]);
                        }
                    });
                }];
            } else {
                RCTExecuteOnMainQueue(^{
                    if (block) {
                        block(image);
                    }
                });
            }
        }];
    } else {
        if (block) {
            block(image);
        }
    }
}

/**
 * 识别图中二维码
 */
RCT_EXPORT_METHOD(detectorQrCode:(NSDictionary *)options resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    if (options == nil) {
        if (reject) {
            reject(@"-1",@"params is null!",nil);
        }
        return;
    }
    if (![options.allKeys containsObject:@"filePath"]) {
        if (reject) {
            reject(@"-1",@"filePath is null!",nil);
        }
        return;
    }
    NSString *filePath = options[@"filePath"];
    [self getImage:filePath finishBlock:^(UIImage *image) {
        RCTExecuteOnMainQueue(^{
            NSString *qrCodeUrl = [self safeDetectorQrCodeImage:image];
            if (qrCodeUrl == nil) {
                qrCodeUrl = [self safeDetectorQrCodeImage:[self scaleQRImage:image widthOrHeight:256]];
            }
            if (qrCodeUrl) {
                // 成功时回调
                if (resolve) {
                    resolve(@{@"data": qrCodeUrl});
                }
            } else {
                if (reject) {
                    reject(@"-1",@"图片二维码识别失败",nil);
                }
            }
        });
    }];
}

@end
